;;; init-package.el --- config for packages

;;; Commentary:
;;; Code:

(use-package benchmark-init
  :init (benchmark-init/activate)
  :hook (after-init . benchmark-init/deactivate))


;;整行删除插件crux C-c k
(use-package crux
  :bind ("C-c k" . crux-smart-kill-line))

;; 删除到最近的非空字符
(use-package hungry-delete
  :bind (("C-c DEL" . hungry-delete-backward)
         ("C-c d" . hungry-delete-forward)))
         
;; 上下移动选中文本块
(use-package drag-stuff
             :bind (("<M-up>" . drag-stuff-up)
                    ("<M-down>" . drag-stuff-down)))

;; ivy-counsel-swiper 文本编辑三剑客
(use-package ivy
  :defer 1
  :demand
  :hook (after-init . ivy-mode)
  :config
  (ivy-mode 1)
  (setq ivy-use-virtual-buffers t
	      ivy-initial-inputs-alist nil
	      ivy-count-format "%d/%d "
	      enable-recursive-minibuffers t
	      ivy-re-builders-alist '((t . ivy--regex-ignore-order))))

(use-package counsel
  :after (ivy)
  :bind (("M-x" . counsel-M-x)
	 ("C-x C-f" . counsel-find-file)
	 ("C-c f" . counsel-recentf)
	 ("C-c g" . counsel-git)))

(use-package swiper
  :after ivy
  :bind (("C-s" . swiper)
	 ("C-r" . swiper-isearch-backward))
  :config (setq swiper-action-recenter t
		swiper-include-line-number-in-search t))

;;自动补全 company
(use-package company
  :hook (after-init . global-company-mode)
  :config (setq company-minimum-prefix-length 1
                company-show-quick-access t))

;; 语法检查工具 flycheck
(use-package flycheck
  :init ;; 在 (require) 之前需要执行的
  (setq flycheck-emacs-lisp-load-path 'inherit)
  :config
  (global-flycheck-mode))

;; git工具安装 magit 
(use-package magit)
;; crux插件
(use-package crux
  :bind (("C-a" . 'crux-move-beginning-of-line)
         ("C-c ^" . 'crux-top-join-line)
         ("C-x ," . 'crux-find-user-init-file)
         ("C-c k" . 'crux-smart-kill-line)))

;; which-key 插件，辅助键位记忆
(use-package which-key
  :defer nil
  :config (which-key-mode))

(use-package projectile
  :ensure t
  :init
  (projectile-mode +1)
  :bind (:map projectile-mode-map
              ("s-p" . projectile-command-map)
              ("C-c p" . projectile-command-map)))

;; miniBuffer交互优化
(use-package ivy-posframe
  :init (setq ivy-posframe-display-functions-alist
	     '((swiper . ivy-posframe-display-at-frame-center)
	       (complete-symbol . ivy-posframe-display-at-point)
	       (counsel-M-x . ivy-posframe-display-at-frame-center)
	       (counsel-find-file . ivy-posframe-display-at-frame-center)
	       (ivy-switch-buffer . ivy-posframe-display-at-frame-center)
	       (t . ivy-posframe-display-at-frame-center)))
  (ivy-posframe-mode 1))

;; 窗口管理工具
(use-package ace-window
  :bind (("M-o" . 'ace-window)))

(use-package edwina
  :config
  ;; 让所有 display-buffer 动作都新增一个 window （而不是复用已经打开此 buffer 的 window）
  (setq display-buffer-base-action '(display-buffer-below-selected))
  ;; 以下定义会被 (edwina-setup-dwm-keys) 增加 'M-' 修饰。
  ;; 我自定义了一套按键，因为原版会把我很常用的 M-d 覆盖掉。
  (setq edwina-dwm-key-alist
        '(("r" edwina-arrange)
          ("j" edwina-select-next-window)
          ("k" edwina-select-previous-window)
          ("J" edwina-swap-next-window)
          ("K" edwina-swap-previous-window)
          ("h" edwina-dec-mfact)    ;; 主窗口缩窄
          ("l" edwina-inc-mfact)    ;; 主窗口拉宽
          ("D" edwina-dec-nmaster)  ;; 减少主窗口的数量
          ("I" edwina-inc-nmaster)  ;; 增加主窗口的数量
          ("C" edwina-delete-window) ;; 关闭窗口
          ("RET" edwina-zoom t)     ;; 交换「主窗口」和「副窗口」
          ("return" edwina-zoom t)
          ("S-RET" edwina-clone-window t) ;; 复制一个本窗口
          ("S-return" edwina-clone-window t)))
  (edwina-setup-dwm-keys)
  (edwina-mode 1))


;; 编程语言代码提示服务器 lsp-mode
(use-package lsp-mode
  ;; 延时加载：仅当 (lsp) 函数被调用时再 (require)
  :commands (lsp)
  ;; 在哪些语言 major mode 下启用 LSP
  :hook (((ruby-mode
           php-mode
           typescript-mode
	   c++-mode
	   c-mode
	   rust-mode
	   css-mode
	   web-mode
	   python-mode
           ;; ......
           ) . lsp))
  :init ;; 在 (reuqire) 之前执行
  (setq lsp-auto-configure t ;; 尝试自动配置自己
        lsp-auto-guess-root t ;; 尝试自动猜测项目根文件夹
        lsp-idle-delay 0.500 ;; 多少时间idle后向服务器刷新信息
        lsp-session-file "~/.emacs/.cache/lsp-sessions") ;; 给缓存文件换一个位置
  )

;; 内容呈现
(use-package lsp-ui
  ;; 仅在某软件包被加载后再加载
  :after (lsp-mode)
  ;; 延时加载
  :commands (lsp-ui-mode)
  :bind
  (:map lsp-ui-mode-map
        ;; 查询符号定义：使用 LSP 来查询。通常是 M-.
        ([remap xref-find-references] . lsp-ui-peek-find-references)
        ;; 查询符号引用：使用 LSP 来查询。通常是 M-?
        ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
        ;; 该文件里的符号列表：类、方法、变量等。前提是语言服务支持本功能。
        ("C-c u" . lsp-ui-imenu))
  ;; 当 lsp 被激活时自动激活 lsp-ui
  :hook (lsp-mode . lsp-ui-mode)
  :init
  ;; lsp-ui 有相当细致的功能开关。具体参考：
  ;; https://github.com/emacs-lsp/lsp-mode/blob/master/docs/tutorials/how-to-turn-off.md
  (setq lsp-enable-symbol-highlighting t
        lsp-ui-doc-enable t
        lsp-lens-enable t))

;; 代码调试插件
(use-package dap-mode
    :init
    (add-hook 'lsp-mode-hook 'dap-mode)
    (add-hook 'dap-mode-hook 'dap-ui-mode)
    (add-hook 'dap-mode-hook 'dap-tooltip-mode)
    ;;   (add-hook 'python-mode-hook (lambda() (require 'dap-python)))
    ;;   (add-hook 'go-mode-hook (lambda() (require 'dap-go)))
    ;;   (add-hook 'java-mode-hook (lambda() (require 'dap-java)))
    )


(use-package restart-emacs)

(provide 'init-package)


;;; init-package.el;;; init-package.el;;; init-package.el
